package com.swu.pad.util.ExcelUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

import com.swu.pad.util.FileDownloadUtil;

@SuppressWarnings("rawtypes")
public class ExcelTemplate {
	// 文件名
	private String fileName;
	// 模板url
	private String templateUrl;
	// 参数
	private Map<String, Object> params;
	// 内容
	private List content;

	private HSSFWorkbook workbook;

	public ExcelTemplate(String fileName, String templateUrl, Map<String, Object> params, List content) {
		this.fileName = fileName;
		this.templateUrl = templateUrl;
		this.params = params;
		this.content = content;
	}

	public void exportExcel(HttpServletResponse response) throws Exception {
		File file = readTemplatePath();
		replaceExpression();
		try {
			FileOutputStream fos = new FileOutputStream(file);
			workbook.write(fos);
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		FileDownloadUtil.download(response, file);
		if (file.isFile() && file.exists()) {
			file.delete();
		}
	}

	/**
	 * 替换Excel中的表达式
	 */
	public void replaceExpression() {
		HSSFSheet sheet = workbook.getSheetAt(0);
		for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
			Row row = sheet.getRow(rowIndex);
			for (Cell cell : row) {
				String cellValue = cell.getStringCellValue().trim();
				Pattern pattern = Pattern.compile("\\$\\{[^\\}]+\\}");
				Matcher matcher = pattern.matcher(cellValue);
				while (matcher.find()) {
					String g = matcher.group().replace("${", "").replace("}", "");
					if (g.startsWith("$.")) {
						if (content != null && !content.isEmpty()) {
							for (int i = 0; i < content.size(); i++) {
								Row lastRow = sheet.getRow(rowIndex + i);
								if (lastRow == null)
									lastRow = sheet.createRow(rowIndex + i);
								String methodName = g.replace("$.", "").substring(0, 1).toUpperCase() + g.replace("$.", "").substring(1);
								Method method = null;
								try {
									method = content.get(i).getClass().getMethod("get" + methodName);
									cellValue = matcher.replaceFirst(method.invoke(content.get(i)) + "");
									lastRow.createCell(cell.getColumnIndex()).setCellValue(cellValue);
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
						}
					} else {
						cellValue = matcher.replaceFirst(params.get(g) + "");
						cell.setCellValue(cellValue);
						matcher = pattern.matcher(cellValue);
					}
				}
			}
		}
	}

	/**
	 * 读取模板文件，返回HSSFWorkbook
	 * @param path
	 * @return 以模板创建的临时文件
	 */
	public File readTemplatePath() {
		File templateFile = new File(templateUrl);
		File fileNew = new File(templateFile.getParent(), fileName);
		if (templateFile.exists()) {
			try {
				FileInputStream fis = new FileInputStream(templateFile);
				FileOutputStream fos = new FileOutputStream(fileNew);
				int read = 0;
				while ((read = fis.read()) != -1) {
					fos.write(read);
					fos.flush();
				}
				fos.close();
				fis.close();
				workbook = new HSSFWorkbook(new FileInputStream(fileNew));
				return fileNew;
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String getTemplateUrl() {
		return templateUrl;
	}

	public void setTempleteUrl(String templateUrl) {
		this.templateUrl = templateUrl;
	}

	public Map<String, Object> getParams() {
		return params;
	}

	public void setParams(Map<String, Object> params) {
		this.params = params;
	}

	public List getContent() {
		return content;
	}

	public void setContent(List content) {
		this.content = content;
	}

}
